/* vim: set ts=2 et sw=2 cindent fo=qroca: */

package com.globant.google.mendoza.command;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.globant.google.malbec.SeleniumBuyerRobot;
import com.globant.google.mendoza.MendozaServer;
import com.globant.google.mendoza.MendozaRequest;
import com.globant.google.mendoza.MendozaServerState;

/** Represents the place order mendoza server command.
 */
public final class MendozaPlaceOrderCommand extends MendozaBaseCommand {

  /** The class logger.
   */
  private static Log log = LogFactory.getLog(MendozaPlaceOrderCommand.class);

  /** The buyer robot used to place the order.
   */
  private SeleniumBuyerRobot buyerRobot;

  /** Creates an instance of MendozaPlaceOrderCommand.
   *
   * @param mendozaRequest The mendoza server request.
   *
   * @param mendoza The mendoza server.
   *
   * @param mendozaState The mendoza server state.
   *
   * @param theBuyerRobot The buyer robot used to place the order.
   */
  public MendozaPlaceOrderCommand(
      final MendozaRequest mendozaRequest, final MendozaServer mendoza,
      final MendozaServerState mendozaState,
      final SeleniumBuyerRobot theBuyerRobot) {
    super(mendozaRequest, mendoza, mendozaState);
    setName("Place order");
    buyerRobot = theBuyerRobot;
  }

  /** Executes the mendoza server place order command.
   */
  public void execute() {
    log.trace("Entering execute");
    MendozaCommandResult result = new MendozaCommandResult();
    String commandResultMsg =
      "OK - Place order command sent to the mendoza server.";
    try {
      placeOrder();
      result.setSuccess(commandResultMsg);
    } catch (RuntimeException e) {
      commandResultMsg =
        e.getMessage().replace("java.lang.RuntimeException:", "");
      result.setError(commandResultMsg);
    }
    setResult(result);
    logCommand(this);
    log.trace("Leaving execute");
  }

  /** Places the order using the buyer robot.
   */
  private void placeOrder() {
    if (missingParameters()) {
      throw new RuntimeException("The order cannot be placed. "
          + "Please, login and checkout a shopping cart first.");
    }
    if (getMendozaState().getCartSignature() != null) {
      MendozaAssertSignatureCommand assertSignatureCmd =
        new MendozaAssertSignatureCommand(null,
            getMendoza(), getMendozaState());
      assertSignatureCmd.execute();
      MendozaCommandResult signatureResult = assertSignatureCmd.getResult();
      if (signatureResult.isError()) {
        String errorMessage = signatureResult.getMessage();
        log.debug(errorMessage);
        log.trace("Leaving placeOrder");
        throw new RuntimeException(errorMessage);
      }
    }
    try {
      String googleOrderNumber = buyerRobot.placeOrder(
          getMendozaState().getShoppingCart(),
          getMendozaState().getBuyerEmail(),
          getMendozaState().getBuyerPassword());
      getMendozaState().setGoogleOrderNumber(googleOrderNumber);
      getMendoza().getMendozaStatus().setGoogleOrderNumber(googleOrderNumber);
      log.debug("Google order number: " + googleOrderNumber);
    } catch (FailingHttpStatusCodeException fhsce) {
      String errorMsg = fhsce.getResponse().getContentAsString();
      log.debug(errorMsg);
      log.trace("Leaving placeOrder");
      throw new RuntimeException(errorMsg);
    } catch (Exception e) {
      log.debug(e.getMessage());
      log.trace("Leaving placeOrder");
      throw new RuntimeException("Place order command FAILED: "
          + e.getMessage());
    }
  }

  /** Cheks if any of the required parameters are null or empty before placing
   * the order.
   *
   * @return Returns true if the order can be placed.
   */
  private boolean missingParameters() {
    if (getMendozaState().getBuyerEmail() == null
        || "".equals(getMendozaState().getBuyerEmail())) {
     return true;
    }
    if (getMendozaState().getBuyerPassword() == null
        || "".equals(getMendozaState().getBuyerPassword())) {
     return true;
    }
    if (getMendozaState().getShoppingCart() == null
        || "".equals(getMendozaState().getShoppingCart())) {
     return true;
    }
    return false;
  }
}

